<!doctype html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8" />
    <title>dependency graph</title>
    <style>
      .node:active path,
.node:hover path,
.node.current path,
.node:active polygon,
.node:hover polygon,
.node.current polygon {
  stroke: fuchsia;
  stroke-width: 2;
}

.edge:active path,
.edge:hover path,
.edge.current path,
.edge:active ellipse,
.edge:hover ellipse,
.edge.current ellipse {
  stroke: url(#edgeGradient);
  stroke-width: 3;
  stroke-opacity: 1;
}

.edge:active polygon,
.edge:hover polygon,
.edge.current polygon {
  stroke: fuchsia;
  stroke-width: 3;
  fill: fuchsia;
  stroke-opacity: 1;
  fill-opacity: 1;
}

.edge:active text,
.edge:hover text {
  fill: fuchsia;
}

.cluster path {
  stroke-width: 3;
}

.cluster:active path,
.cluster:hover path {
  fill: #ffff0011;
}

div.hint {
  background-color: #000000aa;
  color: white;
  font-family: Arial, Helvetica, sans-serif;
  border-radius: 1rem;
  position: fixed;
  top: calc(50% - 4em);
  right: calc(50% - 10em);
  border: none;
  padding: 1em 3em 1em 1em;
}

.hint button {
  position: absolute;
  font-weight: bolder;
  right: 0.6em;
  top: 0.6em;
  color: inherit;
  background-color: inherit;
  border: 1px solid currentColor;
  border-radius: 1em;
  margin-left: 0.6em;
}

.hint a {
  color: inherit;
}

#button_help {
  color: white;
  background-color: #00000011;
  border-radius: 1em;
  position: fixed;
  top: 1em;
  right: 1em;
  font-size: 24pt;
  font-weight: bolder;
  width: 2em;
  height: 2em;
  border: none;
}

#button_help:hover {
  cursor: pointer;
  background-color: #00000077;
}

@media print {
  #button_help {
    display: none;
  }

  div.hint {
    display: none;
  }
}

    </style>
  </head>
  <body>
    <button id="button_help">?</button>
    <div id="hints" class="hint" style="display: none">
      <button id="close-hints">x</button>
      <span id="hint-text"></span>
      <ul>
        <li><b>Hover</b> - highlight</li>
        <li><b>Right-click</b> - pin highlight</li>
        <li><b>ESC</b> - clear</li>
      </ul>
    </div>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
 "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 14.0.4 (20251115.1723)
 -->
<!-- Title: dependency&#45;cruiser output Pages: 1 -->
<svg width="310pt" height="278pt"
 viewBox="0.00 0.00 310.00 278.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 273.75)">
<title>dependency&#45;cruiser output</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-273.75 306,-273.75 306,4 -4,4"/>
<g id="clust1" class="cluster">
<title>cluster_src</title>
<path fill="#ffffff" stroke="black" stroke-width="2" d="M20,-8C20,-8 282,-8 282,-8 288,-8 294,-14 294,-20 294,-20 294,-232 294,-232 294,-238 288,-244 282,-244 282,-244 20,-244 20,-244 14,-244 8,-238 8,-232 8,-232 8,-20 8,-20 8,-14 14,-8 20,-8"/>
<text xml:space="preserve" text-anchor="middle" x="151" y="-231.45" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="9.00">src</text>
</g>
<!-- bin/ -->
<g id="node1" class="node">
<title>bin/</title>
<g id="a_node1"><a xlink:href="https://github.com/sverweij/dependency-cruiser/blob/main/bin/" xlink:title="bin">
<polygon fill="#ffffcc" stroke="black" points="183,-269.75 130.97,-269.75 129,-267.78 129,-252 181.03,-252 183,-253.97 183,-269.75"/>
<polyline fill="none" stroke="black" points="181.03,-267.78 129,-267.78"/>
<polyline fill="none" stroke="black" points="181.03,-267.78 181.03,-252"/>
<polyline fill="none" stroke="black" points="181.03,-267.78 183,-269.75"/>
<text xml:space="preserve" text-anchor="start" x="149.62" y="-257.2" font-family="Helvetica,sans-Serif" font-size="9.00">bin</text>
</a>
</g>
</g>
<!-- src/cli -->
<g id="node2" class="node">
<title>src/cli</title>
<g id="a_node2"><a xlink:href="https://github.com/sverweij/dependency-cruiser/blob/main/src/cli" xlink:title="not&#45;reachable&#45;from&#45;folder&#45;index">
<polygon fill="#ccccff" stroke="blue" points="183,-218.25 130.97,-218.25 129,-216.28 129,-200.5 181.03,-200.5 183,-202.47 183,-218.25"/>
<polyline fill="none" stroke="blue" points="181.03,-216.28 129,-216.28"/>
<polyline fill="none" stroke="blue" points="181.03,-216.28 181.03,-200.5"/>
<polyline fill="none" stroke="blue" points="181.03,-216.28 183,-218.25"/>
<text xml:space="preserve" text-anchor="start" x="151.5" y="-205.7" font-family="Helvetica,sans-Serif" font-size="9.00" fill="blue">cli</text>
</a>
</g>
</g>
<!-- bin/&#45;&gt;src/cli -->
<g id="edge1" class="edge">
<title>bin/&#45;&gt;src/cli</title>
<path fill="none" stroke="#0000ff" stroke-width="2" stroke-opacity="0.466667" d="M156,-251.9C156,-251.9 156,-227.62 156,-227.62"/>
<polygon fill="#0000ff" fill-opacity="0.466667" stroke="#0000ff" stroke-width="2" stroke-opacity="0.466667" points="158.1,-227.62 156,-221.62 153.9,-227.62 158.1,-227.62"/>
</g>
<!-- src/extract -->
<g id="node4" class="node">
<title>src/extract</title>
<g id="a_node4"><a xlink:href="https://github.com/sverweij/dependency-cruiser/blob/main/src/extract" xlink:title="extract">
<polygon fill="#ccffcc" stroke="black" points="272,-95.25 219.97,-95.25 218,-93.28 218,-77.5 270.03,-77.5 272,-79.47 272,-95.25"/>
<polyline fill="none" stroke="black" points="270.03,-93.28 218,-93.28"/>
<polyline fill="none" stroke="black" points="270.03,-93.28 270.03,-77.5"/>
<polyline fill="none" stroke="black" points="270.03,-93.28 272,-95.25"/>
<text xml:space="preserve" text-anchor="start" x="231.5" y="-82.7" font-family="Helvetica,sans-Serif" font-size="9.00">extract</text>
</a>
</g>
</g>
<!-- src/cli&#45;&gt;src/extract -->
<g id="edge8" class="edge">
<title>src/cli&#45;&gt;src/extract</title>
<g id="a_edge8"><a xlink:title="cli&#45;to&#45;main&#45;only">
<path fill="none" stroke="red" stroke-width="2" d="M165,-200.43C165,-186.96 165,-163 165,-163 165,-163 242,-163 242,-163 242,-163 242,-104.49 242,-104.49"/>
<polygon fill="red" stroke="red" stroke-width="2" points="244.1,-104.49 242,-98.49 239.9,-104.49 244.1,-104.49"/>
</a>
</g>
<text xml:space="preserve" text-anchor="middle" x="182.54" y="-164.2" font-family="Helvetica,sans-Serif" font-size="9.00" fill="red">cli&#45;to&#45;main&#45;only</text>
</g>
<!-- src/utl -->
<g id="node5" class="node">
<title>src/utl</title>
<g id="a_node5"><a xlink:href="https://github.com/sverweij/dependency-cruiser/blob/main/src/utl" xlink:title="utl&#45;module&#45;not&#45;shared&#45;enough">
<polygon fill="#cccccc" stroke="blue" points="164,-33.75 111.97,-33.75 110,-31.78 110,-16 162.03,-16 164,-17.97 164,-33.75"/>
<polyline fill="none" stroke="blue" points="162.03,-31.78 110,-31.78"/>
<polyline fill="none" stroke="blue" points="162.03,-31.78 162.03,-16"/>
<polyline fill="none" stroke="blue" points="162.03,-31.78 164,-33.75"/>
<text xml:space="preserve" text-anchor="start" x="132.12" y="-21.2" font-family="Helvetica,sans-Serif" font-size="9.00" fill="blue">utl</text>
</a>
</g>
</g>
<!-- src/cli&#45;&gt;src/utl -->
<g id="edge7" class="edge">
<title>src/cli&#45;&gt;src/utl</title>
<path fill="none" stroke="#aaaaaa" stroke-width="2" stroke-opacity="0.466667" d="M128.58,-212C86.8,-212 12,-212 12,-212 12,-212 12,-22 12,-22 12,-22 100.54,-22 100.54,-22"/>
<polygon fill="#aaaaaa" fill-opacity="0.466667" stroke="#aaaaaa" stroke-width="2" stroke-opacity="0.466667" points="100.54,-24.1 106.54,-22 100.54,-19.9 100.54,-24.1"/>
</g>
<!-- src/config&#45;utl -->
<g id="node7" class="node">
<title>src/config&#45;utl</title>
<g id="a_node7"><a xlink:href="https://github.com/sverweij/dependency-cruiser/blob/main/src/config-utl" xlink:title="config&#45;utl">
<polygon fill="#99ffff" stroke="black" points="286,-187.5 233.97,-187.5 232,-185.53 232,-169.75 284.03,-169.75 286,-171.72 286,-187.5"/>
<polyline fill="none" stroke="black" points="284.03,-185.53 232,-185.53"/>
<polyline fill="none" stroke="black" points="284.03,-185.53 284.03,-169.75"/>
<polyline fill="none" stroke="black" points="284.03,-185.53 286,-187.5"/>
<text xml:space="preserve" text-anchor="start" x="240.25" y="-174.95" font-family="Helvetica,sans-Serif" font-size="9.00">config&#45;utl</text>
</a>
</g>
</g>
<!-- src/cli&#45;&gt;src/config&#45;utl -->
<g id="edge5" class="edge">
<title>src/cli&#45;&gt;src/config&#45;utl</title>
<path fill="none" stroke="#229999" stroke-width="2" stroke-dasharray="5,2" stroke-opacity="0.466667" d="M183.33,-209C213.85,-209 259,-209 259,-209 259,-209 259,-196.93 259,-196.93"/>
<polygon fill="#229999" fill-opacity="0.466667" stroke="#229999" stroke-width="2" stroke-opacity="0.466667" points="261.1,-196.93 259,-190.93 256.9,-196.93 261.1,-196.93"/>
</g>
<!-- src/main -->
<g id="node8" class="node">
<title>src/main</title>
<g id="a_node8"><a xlink:href="https://github.com/sverweij/dependency-cruiser/blob/main/src/main" xlink:title="main">
<polygon fill="#ffcccc" stroke="black" points="183,-156.75 130.97,-156.75 129,-154.78 129,-139 181.03,-139 183,-140.97 183,-156.75"/>
<polyline fill="none" stroke="black" points="181.03,-154.78 129,-154.78"/>
<polyline fill="none" stroke="black" points="181.03,-154.78 181.03,-139"/>
<polyline fill="none" stroke="black" points="181.03,-154.78 183,-156.75"/>
<text xml:space="preserve" text-anchor="start" x="145.88" y="-144.2" font-family="Helvetica,sans-Serif" font-size="9.00">main</text>
</a>
</g>
</g>
<!-- src/cli&#45;&gt;src/main -->
<g id="edge6" class="edge">
<title>src/cli&#45;&gt;src/main</title>
<path fill="none" stroke="#770000" stroke-width="2" stroke-opacity="0.466667" d="M147,-200.03C147,-200.03 147,-165.93 147,-165.93"/>
<polygon fill="#770000" fill-opacity="0.466667" stroke="#770000" stroke-width="2" stroke-opacity="0.466667" points="149.1,-165.93 147,-159.93 144.9,-165.93 149.1,-165.93"/>
</g>
<!-- src/report -->
<g id="node9" class="node">
<title>src/report</title>
<g id="a_node9"><a xlink:href="https://github.com/sverweij/dependency-cruiser/blob/main/src/report" xlink:title="report">
<polygon fill="#ffccff" stroke="black" points="150,-95.25 97.97,-95.25 96,-93.28 96,-77.5 148.03,-77.5 150,-79.47 150,-95.25"/>
<polyline fill="none" stroke="black" points="148.03,-93.28 96,-93.28"/>
<polyline fill="none" stroke="black" points="148.03,-93.28 148.03,-77.5"/>
<polyline fill="none" stroke="black" points="148.03,-93.28 150,-95.25"/>
<text xml:space="preserve" text-anchor="start" x="111" y="-82.7" font-family="Helvetica,sans-Serif" font-size="9.00">report</text>
</a>
</g>
</g>
<!-- src/cli&#45;&gt;src/report -->
<g id="edge9" class="edge">
<title>src/cli&#45;&gt;src/report</title>
<path fill="none" stroke="#ff00ff" stroke-width="2" stroke-opacity="0.466667" d="M128.76,-206C126.76,-206 125.5,-206 125.5,-206 125.5,-206 125.5,-104.39 125.5,-104.39"/>
<polygon fill="#ff00ff" fill-opacity="0.466667" stroke="#ff00ff" stroke-width="2" stroke-opacity="0.466667" points="127.6,-104.39 125.5,-98.39 123.4,-104.39 127.6,-104.39"/>
</g>
<!-- src/cache -->
<g id="node3" class="node">
<title>src/cache</title>
<g id="a_node3"><a xlink:href="https://github.com/sverweij/dependency-cruiser/blob/main/src/cache" xlink:title="cache">
<polygon fill="#ffffcc" stroke="black" points="230,-126 177.97,-126 176,-124.03 176,-108.25 228.03,-108.25 230,-110.22 230,-126"/>
<polyline fill="none" stroke="black" points="228.03,-124.03 176,-124.03"/>
<polyline fill="none" stroke="black" points="228.03,-124.03 228.03,-108.25"/>
<polyline fill="none" stroke="black" points="228.03,-124.03 230,-126"/>
<text xml:space="preserve" text-anchor="start" x="190.62" y="-113.45" font-family="Helvetica,sans-Serif" font-size="9.00">cache</text>
</a>
</g>
</g>
<!-- src/cache&#45;&gt;src/extract -->
<g id="edge2" class="edge">
<title>src/cache&#45;&gt;src/extract</title>
<path fill="none" stroke="#007700" stroke-width="2" stroke-opacity="0.466667" d="M224,-108.07C224,-108.07 224,-104.5 224,-104.5"/>
<polygon fill="#007700" fill-opacity="0.466667" stroke="#007700" stroke-width="2" stroke-opacity="0.466667" points="226.1,-104.5 224,-98.5 221.9,-104.5 226.1,-104.5"/>
</g>
<!-- src/cache&#45;&gt;src/utl -->
<g id="edge3" class="edge">
<title>src/cache&#45;&gt;src/utl</title>
<path fill="none" stroke="#aaaaaa" stroke-width="2" stroke-opacity="0.466667" d="M211,-108.03C211,-85.51 211,-29 211,-29 211,-29 173.16,-29 173.16,-29"/>
<polygon fill="#aaaaaa" fill-opacity="0.466667" stroke="#aaaaaa" stroke-width="2" stroke-opacity="0.466667" points="173.16,-26.9 167.16,-29 173.16,-31.1 173.16,-26.9"/>
</g>
<!-- src/graph&#45;utl -->
<g id="node6" class="node">
<title>src/graph&#45;utl</title>
<g id="a_node6"><a xlink:href="https://github.com/sverweij/dependency-cruiser/blob/main/src/graph-utl" xlink:title="graph&#45;utl">
<polygon fill="#ffcccc" stroke="black" points="204,-64.5 151.97,-64.5 150,-62.53 150,-46.75 202.03,-46.75 204,-48.72 204,-64.5"/>
<polyline fill="none" stroke="black" points="202.03,-62.53 150,-62.53"/>
<polyline fill="none" stroke="black" points="202.03,-62.53 202.03,-46.75"/>
<polyline fill="none" stroke="black" points="202.03,-62.53 204,-64.5"/>
<text xml:space="preserve" text-anchor="start" x="158.62" y="-51.95" font-family="Helvetica,sans-Serif" font-size="9.00">graph&#45;utl</text>
</a>
</g>
</g>
<!-- src/cache&#45;&gt;src/graph&#45;utl -->
<g id="edge4" class="edge">
<title>src/cache&#45;&gt;src/graph&#45;utl</title>
<path fill="none" stroke="#770000" stroke-width="2" stroke-opacity="0.466667" d="M185.33,-107.78C185.33,-107.78 185.33,-73.68 185.33,-73.68"/>
<polygon fill="#770000" fill-opacity="0.466667" stroke="#770000" stroke-width="2" stroke-opacity="0.466667" points="187.43,-73.68 185.33,-67.68 183.23,-73.68 187.43,-73.68"/>
</g>
<!-- src/extract&#45;&gt;src/utl -->
<g id="edge16" class="edge">
<title>src/extract&#45;&gt;src/utl</title>
<path fill="none" stroke="#aaaaaa" stroke-width="2" stroke-opacity="0.466667" d="M245,-77.05C245,-59.88 245,-25 245,-25 245,-25 173.28,-25 173.28,-25"/>
<polygon fill="#aaaaaa" fill-opacity="0.466667" stroke="#aaaaaa" stroke-width="2" stroke-opacity="0.466667" points="173.28,-22.9 167.28,-25 173.28,-27.1 173.28,-22.9"/>
</g>
<!-- src/extract&#45;&gt;src/graph&#45;utl -->
<g id="edge17" class="edge">
<title>src/extract&#45;&gt;src/graph&#45;utl</title>
<path fill="none" stroke="#770000" stroke-width="2" stroke-opacity="0.466667" d="M217.77,-86C205.91,-86 194.67,-86 194.67,-86 194.67,-86 194.67,-73.93 194.67,-73.93"/>
<polygon fill="#770000" fill-opacity="0.466667" stroke="#770000" stroke-width="2" stroke-opacity="0.466667" points="196.77,-73.93 194.67,-67.93 192.57,-73.93 196.77,-73.93"/>
</g>
<!-- src/graph&#45;utl&#45;&gt;src/utl -->
<g id="edge18" class="edge">
<title>src/graph&#45;utl&#45;&gt;src/utl</title>
<path fill="none" stroke="#aaaaaa" stroke-width="2" stroke-opacity="0.466667" d="M157,-46.57C157,-46.57 157,-43 157,-43"/>
<polygon fill="#aaaaaa" fill-opacity="0.466667" stroke="#aaaaaa" stroke-width="2" stroke-opacity="0.466667" points="159.1,-43 157,-37 154.9,-43 159.1,-43"/>
</g>
<!-- src/config&#45;utl&#45;&gt;src/extract -->
<g id="edge10" class="edge">
<title>src/config&#45;utl&#45;&gt;src/extract</title>
<path fill="none" stroke="#007700" stroke-width="2" stroke-opacity="0.466667" d="M262,-169.44C262,-169.44 262,-104.55 262,-104.55"/>
<polygon fill="#007700" fill-opacity="0.466667" stroke="#007700" stroke-width="2" stroke-opacity="0.466667" points="264.1,-104.55 262,-98.55 259.9,-104.55 264.1,-104.55"/>
</g>
<!-- src/config&#45;utl&#45;&gt;src/utl -->
<g id="edge12" class="edge">
<title>src/config&#45;utl&#45;&gt;src/utl</title>
<path fill="none" stroke="#aaaaaa" stroke-width="2" stroke-opacity="0.466667" d="M279,-169.64C279,-136.09 279,-20 279,-20 279,-20 173.41,-20 173.41,-20"/>
<polygon fill="#aaaaaa" fill-opacity="0.466667" stroke="#aaaaaa" stroke-width="2" stroke-opacity="0.466667" points="173.41,-17.9 167.41,-20 173.41,-22.1 173.41,-17.9"/>
</g>
<!-- src/config&#45;utl&#45;&gt;src/main -->
<g id="edge11" class="edge">
<title>src/config&#45;utl&#45;&gt;src/main</title>
<path fill="none" stroke="#770000" stroke-width="2" stroke-opacity="0.466667" d="M252,-169.27C252,-160.26 252,-148 252,-148 252,-148 192.28,-148 192.28,-148"/>
<polygon fill="#770000" fill-opacity="0.466667" stroke="#770000" stroke-width="2" stroke-opacity="0.466667" points="192.28,-145.9 186.28,-148 192.28,-150.1 192.28,-145.9"/>
</g>
<!-- src/main&#45;&gt;src/cache -->
<g id="edge20" class="edge">
<title>src/main&#45;&gt;src/cache</title>
<path fill="none" stroke="#000000" stroke-width="2" stroke-dasharray="5,2" stroke-opacity="0.200000" d="M179.5,-138.82C179.5,-138.82 179.5,-135.25 179.5,-135.25"/>
<polygon fill="#000000" fill-opacity="0.200000" stroke="#000000" stroke-width="2" stroke-opacity="0.200000" points="181.6,-135.25 179.5,-129.25 177.4,-135.25 181.6,-135.25"/>
</g>
<!-- src/main&#45;&gt;src/extract -->
<g id="edge19" class="edge">
<title>src/main&#45;&gt;src/extract</title>
<path fill="none" stroke="#007700" stroke-width="2" stroke-opacity="0.466667" d="M170.8,-138.74C170.8,-122.66 170.8,-91 170.8,-91 170.8,-91 208.76,-91 208.76,-91"/>
<polygon fill="#007700" fill-opacity="0.466667" stroke="#007700" stroke-width="2" stroke-opacity="0.466667" points="208.76,-93.1 214.76,-91 208.76,-88.9 208.76,-93.1"/>
</g>
<!-- src/main&#45;&gt;src/utl -->
<g id="edge23" class="edge">
<title>src/main&#45;&gt;src/utl</title>
<path fill="none" stroke="#aaaaaa" stroke-width="2" stroke-opacity="0.466667" d="M155.2,-138.75C155.2,-118.39 155.2,-71 155.2,-71 155.2,-71 140,-71 140,-71 140,-71 140,-43.24 140,-43.24"/>
<polygon fill="#aaaaaa" fill-opacity="0.466667" stroke="#aaaaaa" stroke-width="2" stroke-opacity="0.466667" points="142.1,-43.24 140,-37.24 137.9,-43.24 142.1,-43.24"/>
</g>
<!-- src/main&#45;&gt;src/graph&#45;utl -->
<g id="edge24" class="edge">
<title>src/main&#45;&gt;src/graph&#45;utl</title>
<path fill="none" stroke="#770000" stroke-width="2" stroke-opacity="0.466667" d="M165.6,-138.69C165.6,-138.69 165.6,-73.8 165.6,-73.8"/>
<polygon fill="#770000" fill-opacity="0.466667" stroke="#770000" stroke-width="2" stroke-opacity="0.466667" points="167.7,-73.8 165.6,-67.8 163.5,-73.8 167.7,-73.8"/>
</g>
<!-- src/main&#45;&gt;src/report -->
<g id="edge22" class="edge">
<title>src/main&#45;&gt;src/report</title>
<path fill="none" stroke="#ff00ff" stroke-width="2" stroke-opacity="0.466667" d="M143,-138.53C143,-138.53 143,-104.43 143,-104.43"/>
<polygon fill="#ff00ff" fill-opacity="0.466667" stroke="#ff00ff" stroke-width="2" stroke-opacity="0.466667" points="145.1,-104.43 143,-98.43 140.9,-104.43 145.1,-104.43"/>
</g>
<!-- src/enrich -->
<g id="node10" class="node">
<title>src/enrich</title>
<g id="a_node10"><a xlink:href="https://github.com/sverweij/dependency-cruiser/blob/main/src/enrich" xlink:title="enrich">
<polygon fill="#77eeaa" stroke="black" points="84,-95.25 31.97,-95.25 30,-93.28 30,-77.5 82.03,-77.5 84,-79.47 84,-95.25"/>
<polyline fill="none" stroke="black" points="82.03,-93.28 30,-93.28"/>
<polyline fill="none" stroke="black" points="82.03,-93.28 82.03,-77.5"/>
<polyline fill="none" stroke="black" points="82.03,-93.28 84,-95.25"/>
<text xml:space="preserve" text-anchor="start" x="44.25" y="-82.7" font-family="Helvetica,sans-Serif" font-size="9.00">enrich</text>
</a>
</g>
</g>
<!-- src/main&#45;&gt;src/enrich -->
<g id="edge21" class="edge">
<title>src/main&#45;&gt;src/enrich</title>
<path fill="none" stroke="#007766" stroke-width="2" stroke-dasharray="5,2" stroke-opacity="0.466667" d="M128.72,-148C97.02,-148 49,-148 49,-148 49,-148 49,-104.76 49,-104.76"/>
<polygon fill="#007766" fill-opacity="0.466667" stroke="#007766" stroke-width="2" stroke-opacity="0.466667" points="51.1,-104.76 49,-98.76 46.9,-104.76 51.1,-104.76"/>
</g>
<!-- src/schema -->
<g id="node12" class="node">
<title>src/schema</title>
<g id="a_node12"><a xlink:href="https://github.com/sverweij/dependency-cruiser/blob/main/src/schema" xlink:title="not&#45;unreachable&#45;from&#45;cli">
<polygon fill="#ccffcc" stroke="red" points="122,-126 69.97,-126 68,-124.03 68,-108.25 120.03,-108.25 122,-110.22 122,-126"/>
<polyline fill="none" stroke="red" points="120.03,-124.03 68,-124.03"/>
<polyline fill="none" stroke="red" points="120.03,-124.03 120.03,-108.25"/>
<polyline fill="none" stroke="red" points="120.03,-124.03 122,-126"/>
<text xml:space="preserve" text-anchor="start" x="78.88" y="-113.45" font-family="Helvetica,sans-Serif" font-size="9.00" fill="red">schema</text>
</a>
</g>
</g>
<!-- src/main&#45;&gt;src/schema -->
<g id="edge25" class="edge">
<title>src/main&#45;&gt;src/schema</title>
<path fill="none" stroke="#000000" stroke-width="2" stroke-opacity="0.200000" d="M136,-138.78C136,-129.67 136,-117 136,-117 136,-117 131.15,-117 131.15,-117"/>
<polygon fill="#000000" fill-opacity="0.200000" stroke="#000000" stroke-width="2" stroke-opacity="0.200000" points="131.15,-114.9 125.15,-117 131.15,-119.1 131.15,-114.9"/>
</g>
<!-- src/report&#45;&gt;src/utl -->
<g id="edge27" class="edge">
<title>src/report&#45;&gt;src/utl</title>
<path fill="none" stroke="#aaaaaa" stroke-width="2" stroke-opacity="0.466667" d="M130,-77.03C130,-77.03 130,-42.93 130,-42.93"/>
<polygon fill="#aaaaaa" fill-opacity="0.466667" stroke="#aaaaaa" stroke-width="2" stroke-opacity="0.466667" points="132.1,-42.93 130,-36.93 127.9,-42.93 132.1,-42.93"/>
</g>
<!-- src/report&#45;&gt;src/graph&#45;utl -->
<g id="edge26" class="edge">
<title>src/report&#45;&gt;src/graph&#45;utl</title>
<path fill="none" stroke="#770000" stroke-width="2" stroke-opacity="0.466667" d="M150.18,-82C155.98,-82 160.4,-82 160.4,-82 160.4,-82 160.4,-73.88 160.4,-73.88"/>
<polygon fill="#770000" fill-opacity="0.466667" stroke="#770000" stroke-width="2" stroke-opacity="0.466667" points="162.5,-73.88 160.4,-67.88 158.3,-73.88 162.5,-73.88"/>
</g>
<!-- src/enrich&#45;&gt;src/utl -->
<g id="edge14" class="edge">
<title>src/enrich&#45;&gt;src/utl</title>
<path fill="none" stroke="#aaaaaa" stroke-width="2" stroke-opacity="0.466667" d="M84.25,-83C87.67,-83 90,-83 90,-83 90,-83 90,-28 90,-28 90,-28 100.63,-28 100.63,-28"/>
<polygon fill="#aaaaaa" fill-opacity="0.466667" stroke="#aaaaaa" stroke-width="2" stroke-opacity="0.466667" points="100.63,-30.1 106.63,-28 100.63,-25.9 100.63,-30.1"/>
</g>
<!-- src/enrich&#45;&gt;src/graph&#45;utl -->
<g id="edge13" class="edge">
<title>src/enrich&#45;&gt;src/graph&#45;utl</title>
<path fill="none" stroke="#770000" stroke-width="2" stroke-opacity="0.466667" d="M84.29,-89C89.31,-89 93,-89 93,-89 93,-89 93,-59 93,-59 93,-59 140.93,-59 140.93,-59"/>
<polygon fill="#770000" fill-opacity="0.466667" stroke="#770000" stroke-width="2" stroke-opacity="0.466667" points="140.93,-61.1 146.93,-59 140.93,-56.9 140.93,-61.1"/>
</g>
<!-- src/validate -->
<g id="node11" class="node">
<title>src/validate</title>
<g id="a_node11"><a xlink:href="https://github.com/sverweij/dependency-cruiser/blob/main/src/validate" xlink:title="validate">
<polygon fill="#ccccff" stroke="black" points="87,-64.5 34.97,-64.5 33,-62.53 33,-46.75 85.03,-46.75 87,-48.72 87,-64.5"/>
<polyline fill="none" stroke="black" points="85.03,-62.53 33,-62.53"/>
<polyline fill="none" stroke="black" points="85.03,-62.53 85.03,-46.75"/>
<polyline fill="none" stroke="black" points="85.03,-62.53 87,-64.5"/>
<text xml:space="preserve" text-anchor="start" x="43.88" y="-51.95" font-family="Helvetica,sans-Serif" font-size="9.00">validate</text>
</a>
</g>
</g>
<!-- src/enrich&#45;&gt;src/validate -->
<g id="edge15" class="edge">
<title>src/enrich&#45;&gt;src/validate</title>
<path fill="none" stroke="#0000ff" stroke-width="2" stroke-opacity="0.466667" d="M58.5,-77.32C58.5,-77.32 58.5,-73.75 58.5,-73.75"/>
<polygon fill="#0000ff" fill-opacity="0.466667" stroke="#0000ff" stroke-width="2" stroke-opacity="0.466667" points="60.6,-73.75 58.5,-67.75 56.4,-73.75 60.6,-73.75"/>
</g>
<!-- src/validate&#45;&gt;src/utl -->
<g id="edge28" class="edge">
<title>src/validate&#45;&gt;src/utl</title>
<path fill="none" stroke="#aaaaaa" stroke-width="2" stroke-opacity="0.466667" d="M87.19,-53C103.07,-53 120,-53 120,-53 120,-53 120,-43.11 120,-43.11"/>
<polygon fill="#aaaaaa" fill-opacity="0.466667" stroke="#aaaaaa" stroke-width="2" stroke-opacity="0.466667" points="122.1,-43.11 120,-37.11 117.9,-43.11 122.1,-43.11"/>
</g>
</g>
</svg>
    <script>
      var gMode = new Mode();

var title2ElementMap = (function makeElementMap() {
  /** @type {NodeListOf<SVGGElement>} */
  var nodes = document.querySelectorAll(".node");
  /** @type {NodeListOf<SVGGElement>} */
  var edges = document.querySelectorAll(".edge");
  return new Title2ElementMap(edges, nodes);
})();

function getHoverHandler(pTitle2ElementMap) {
  /** @type {string} */
  var currentHighlightedTitle = "";

  /** @param {MouseEvent} pMouseEvent */
  return function hoverHighlightHandler(pMouseEvent) {
    var closestNodeOrEdge = pMouseEvent.target.closest(".edge, .node");
    var closestTitleText = getTitleText(closestNodeOrEdge);

    if (
      currentHighlightedTitle !== closestTitleText &&
      gMode.get() === gMode.HOVER
    ) {
      resetNodesAndEdges();
      addHighlight(closestNodeOrEdge);
      pTitle2ElementMap.get(closestTitleText).forEach(addHighlight);
      currentHighlightedTitle = closestTitleText;
    }
  };
}

function getSelectHandler(pTitle2ElementMap) {
  /** @type {string} */
  var currentHighlightedTitle = "";

  /** @param {MouseEvent} pMouseEvent */
  return function selectHighlightHandler(pMouseEvent) {
    pMouseEvent.preventDefault();

    var closestNodeOrEdge = pMouseEvent.target.closest(".edge, .node");
    var closestTitleText = getTitleText(closestNodeOrEdge);

    if (closestNodeOrEdge) {
      gMode.setToSelect();
    } else {
      gMode.setToHover();
    }
    if (currentHighlightedTitle !== closestTitleText) {
      resetNodesAndEdges();
      addHighlight(closestNodeOrEdge);
      pTitle2ElementMap.get(closestTitleText).forEach(addHighlight);
      currentHighlightedTitle = closestTitleText;
    }
  };
}
function Mode() {
  var HOVER = 1;
  var SELECT = 2;

  function setToHover() {
    this._mode = HOVER;
  }
  function setToSelect() {
    this._mode = SELECT;
  }

  /**
   * @returns {number}
   */
  function get() {
    return this._mode || HOVER;
  }

  return {
    HOVER: HOVER,
    SELECT: SELECT,
    setToHover: setToHover,
    setToSelect: setToSelect,
    get: get,
  };
}

/**
 *
 * @param {SVGGelement[]} pEdges
 * @param {SVGGElement[]} pNodes
 * @return {{get: (pTitleText:string) => SVGGElement[]}}
 */
function Title2ElementMap(pEdges, pNodes) {
  /* {{[key: string]: SVGGElement[]}} */
  var elementMap = buildMap(pEdges, pNodes);

  /**
   * @param {NodeListOf<SVGGElement>} pEdges
   * @param {NodeListOf<SVGGElement>} pNodes
   * @return {{[key: string]: SVGGElement[]}}
   */
  function buildMap(pEdges, pNodes) {
    var title2NodeMap = buildTitle2NodeMap(pNodes);

    return nodeListToArray(pEdges).reduce(addEdgeToMap(title2NodeMap), {});
  }
  /**
   * @param {NodeListOf<SVGGElement>} pNodes
   * @return {{[key: string]: SVGGElement}}
   */
  function buildTitle2NodeMap(pNodes) {
    return nodeListToArray(pNodes).reduce(addNodeToMap, {});
  }

  function addNodeToMap(pMap, pNode) {
    var titleText = getTitleText(pNode);

    if (titleText) {
      pMap[titleText] = pNode;
    }
    return pMap;
  }

  function addEdgeToMap(pNodeMap) {
    return function (pEdgeMap, pEdge) {
      /** @type {string} */
      var titleText = getTitleText(pEdge);

      if (titleText) {
        var edge = pryEdgeFromTitle(titleText);

        pEdgeMap[titleText] = [pNodeMap[edge.from], pNodeMap[edge.to]];
        (pEdgeMap[edge.from] || (pEdgeMap[edge.from] = [])).push(pEdge);
        (pEdgeMap[edge.to] || (pEdgeMap[edge.to] = [])).push(pEdge);
      }
      return pEdgeMap;
    };
  }

  /**
   *
   * @param {string} pString
   * @return {{from?: string; to?:string;}}
   */
  function pryEdgeFromTitle(pString) {
    var nodeNames = pString.split(/\s*->\s*/);

    return {
      from: nodeNames.shift(),
      to: nodeNames.shift(),
    };
  }
  /**
   *
   * @param {string} pTitleText
   * @return {SVGGElement[]}
   */
  function get(pTitleText) {
    return (pTitleText && elementMap[pTitleText]) || [];
  }
  return {
    get: get,
  };
}

/**
 * @param {SVGGElement} pGElement
 * @return {string?}
 */
function getTitleText(pGElement) {
  /** @type {SVGTitleElement} */
  var title = pGElement && pGElement.querySelector("title");
  /** @type {string} */
  var titleText = title && title.textContent;

  if (titleText) {
    titleText = titleText.trim();
  }
  return titleText;
}

/**
 * @param {NodeListOf<Element>} pNodeList
 * @return {Element[]}
 */
function nodeListToArray(pNodeList) {
  var lReturnValue = [];

  pNodeList.forEach(function (pElement) {
    lReturnValue.push(pElement);
  });

  return lReturnValue;
}

function resetNodesAndEdges() {
  nodeListToArray(document.querySelectorAll(".current")).forEach(
    removeHighlight,
  );
}

/**
 * @param {SVGGElement} pGElement
 */
function removeHighlight(pGElement) {
  if (pGElement && pGElement.classList) {
    pGElement.classList.remove("current");
  }
}

/**
 * @param {SVGGElement} pGroup
 */
function addHighlight(pGroup) {
  if (pGroup && pGroup.classList) {
    pGroup.classList.add("current");
  }
}

var gHints = {
  HIDDEN: 1,
  SHOWN: 2,
  state: 1, // === HIDDEN
  show: function () {
    document.getElementById("hints").removeAttribute("style");
    gHints.state = gHints.SHOWN;
  },
  hide: function () {
    document.getElementById("hints").style = "display:none";
    gHints.state = gHints.HIDDEN;
  },
  toggle: function () {
    if ((gHints.state || gHints.HIDDEN) === gHints.HIDDEN) {
      gHints.show();
    } else {
      gHints.hide();
    }
  },
};

/** @param {KeyboardEvent} pKeyboardEvent */
function keyboardEventHandler(pKeyboardEvent) {
  if (pKeyboardEvent.key === "Escape") {
    resetNodesAndEdges();
    gMode.setToHover();
    gHints.hide();
  }
  if (pKeyboardEvent.key === "F1") {
    pKeyboardEvent.preventDefault();
    gHints.toggle();
  }
}

document.addEventListener("contextmenu", getSelectHandler(title2ElementMap));
document.addEventListener("mouseover", getHoverHandler(title2ElementMap));
document.addEventListener("keydown", keyboardEventHandler);
document.getElementById("close-hints").addEventListener("click", gHints.hide);
document.getElementById("button_help").addEventListener("click", gHints.toggle);
document.querySelector("svg").insertAdjacentHTML(
  "afterbegin",
  `<linearGradient id="edgeGradient">
      <stop offset="0%" stop-color="fuchsia"/>
      <stop offset="100%" stop-color="purple"/>
   </linearGradient>
  `,
);

// Add a small increment to the last value of the path to make gradients on
// horizontal paths work. Without them all browsers I tested with (firefox,
// chrome) do not render the gradient, but instead make the line transparent
// (or the color of the background, I haven't looked into it that deeply,
// but for the hack it doesn't matter which).
function skewLineABit(lDrawingInstructions) {
  var lLastValue = lDrawingInstructions.match(/(\d+\.?\d*)$/)[0];
  // Smaller values than .001 _should_ work as well, but don't in all
  // cases. Even this value is so small that it is not visible to the
  // human eye (tested with the two I have at my disposal).
  var lIncrement = 0.001;
  var lNewLastValue = parseFloat(lLastValue) + lIncrement;

  return lDrawingInstructions.replace(lLastValue, lNewLastValue);
}

nodeListToArray(document.querySelectorAll("path"))
  .filter(function (pElement) {
    return pElement.parentElement.classList.contains("edge");
  })
  .forEach(function (pElement) {
    pElement.attributes.d.value = skewLineABit(pElement.attributes.d.value);
  });

    </script>
  </body>
</html>
